package com.example.demo.mbp;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.demo.mbp.entity.CommonQueryRequest;
import com.example.demo.mbp.entity.QueryCondition;
import com.example.demo.mbp.entity.QueryGroup;
import com.example.demo.mbp.entity.SortInfo;

import java.util.List;
import java.util.regex.Pattern;

/**
 *
 * 当嵌套使用拼接查询条件时，参数占位符可能会重复，
 * 导致 SQL 参数绑定错误。这是因为 MyBatis-Plus 内部使用计数器生成占位符名称（如MPGENVAL1），
 * 而在递归构建条件时如果每次新建QueryWrapper，计数器并未累计，而是从1开始。生成如下代码（其中ew.paramNameValuePairs.MPGENVAL1出现了两次，来源于两个QueryWrapper）：
 *
 * 使用QueryWrapper对象递归拼接可以解决此问题
 *示例：
 * 请求参数：
 *   {
 *   "queryGroup": {
 *     "connector": "or",
 *     "conditions": [
 *       { "field": "id", "operator": "eq", "value": "1927309147753762817" }
 *     ],
 *     "groups": [
 *       {
 *         "connector": "and",
 *         "conditions": [
 *           { "field": "name", "operator": "like", "value": "向量" },
 *           { "field": "name", "operator": "like", "value": "Spark" }
 *         ]
 *       }
 *     ]
 *   },
 *   "sortInfos": [
 *     { "field": "type", "direction": "desc", "naturalSort": false }
 *   ]
 * }
 * 生成的sql:
 *      WHERE (id = #{ew.paramNameValuePairs.MPGENVAL1}
 *      OR ((name LIKE #{ew.paramNameValuePairs.MPGENVAL1} AND name LIKE #{ew.paramNameValuePairs.MPGENVAL2}))) ORDER BY type DESC
 *
 **/

/**
 * 单表简单查询封装
 * <p>创建时间: 2025/5/29 </p>
 *
 * @author: <a href="mail to: 952281157@qq.com" rel="nofollow">zhaozhizheng</a>
 * @version: 1.0
 * @update [序号][日期YYYY-MM-DD] [更改人姓名][变更描述]
 **/
public class BeanToQueryWrapper {


    // 允许排序的字段白名单（防止SQL注入）
    private static final Pattern ALLOWED_SORT_FIELDS = Pattern.compile("^(id|username|age|email|address|createTime|updateTime)$");
    // 允许查询的字段白名单
    private static final Pattern ALLOWED_QUERY_FIELDS = Pattern.compile("^(id|username|age|email|address|createTime|updateTime)$");


    public static <T> QueryWrapper<T> queryByCondition(CommonQueryRequest request, Class<T> entityClass) {
        // 构建查询条件
        QueryWrapper<T> wrapper = buildQueryWrapper(request.getQueryGroup());
        // 应用排序
        applySort(wrapper, request.getSortInfos());
        return wrapper;
    }

    /**
     * 递归构建查询条件
     */
    private static <T> QueryWrapper<T> buildQueryWrapper(QueryGroup queryGroup) {
        QueryWrapper<T> wrapper = new QueryWrapper<>();

        if (queryGroup == null) {
            return wrapper;
        }

        // 处理条件列表
        if (queryGroup.getConditions() != null && !queryGroup.getConditions().isEmpty()) {
            for (QueryCondition condition : queryGroup.getConditions()) {
                applyCondition(wrapper, condition);
            }
        }

        // 递归处理子查询组
        if (queryGroup.getGroups() != null && !queryGroup.getGroups().isEmpty()) {
            for (QueryGroup subGroup : queryGroup.getGroups()) {
                if ("and".equalsIgnoreCase(queryGroup.getConnector())) {
                    // 使用Lambda表达式递归构建AND条件
                    wrapper.and(w -> buildSubWrapper(w, subGroup));
                } else {
                    // 使用Lambda表达式递归构建OR条件
                    wrapper.or(w -> buildSubWrapper(w, subGroup));
                }
            }
        }

        return wrapper;
    }

    /**
     * 构建子查询条件
     */
    private static <T> void buildSubWrapper(QueryWrapper<T> wrapper, QueryGroup subGroup) {
        // 处理子查询的条件列表
        if (subGroup.getConditions() != null && !subGroup.getConditions().isEmpty()) {
            for (QueryCondition condition : subGroup.getConditions()) {
                applyCondition(wrapper, condition);
            }
        }

        // 递归处理子查询的子组
        if (subGroup.getGroups() != null && !subGroup.getGroups().isEmpty()) {
            for (QueryGroup subSubGroup : subGroup.getGroups()) {
                if ("and".equalsIgnoreCase(subGroup.getConnector())) {
                    wrapper.and(w -> buildSubWrapper(w, subSubGroup));
                } else {
                    wrapper.or(w -> buildSubWrapper(w, subSubGroup));
                }
            }
        }
    }

    /**
     * 应用单个查询条件
     */
    private static <T> void applyCondition(QueryWrapper<T> wrapper, QueryCondition condition) {
        if (condition == null || !isValidField(condition.getField()) || condition.getValue() == null) {
            return;
        }

        String field = condition.getField();
        Object value = condition.getValue();

        switch (condition.getOperator().toLowerCase()) {
            case "eq":
                wrapper.eq(field, value);
                break;
            case "ne":
                wrapper.ne(field, value);
                break;
            case "gt":
                wrapper.gt(field, value);
                break;
            case "ge":
                wrapper.ge(field, value);
                break;
            case "lt":
                wrapper.lt(field, value);
                break;
            case "le":
                wrapper.le(field, value);
                break;
            case "in":
                if (value instanceof List) {
                    wrapper.in(field, (List<?>) value);
                }
                break;
            case "notin":
                if (value instanceof List) {
                    wrapper.notIn(field, (List<?>) value);
                }
                break;
            case "like":
                wrapper.like(field, value);
                break;
            case "leftlike":
                wrapper.likeLeft(field, value.toString());
                break;
            case "rightlike":
                wrapper.likeRight(field, value.toString());
                break;
            default:
                // 忽略不支持的操作符
                break;
        }
    }

    /**
     * 应用排序条件
     */
    private static <T> void applySort(QueryWrapper<T> wrapper, List<SortInfo> sortInfos) {
        if (sortInfos == null || sortInfos.isEmpty()) {
            return;
        }

        for (SortInfo sortInfo : sortInfos) {
            if (!isValidSortField(sortInfo.getField())) {
                continue; // 忽略非法字段
            }

            boolean isAsc = "asc".equalsIgnoreCase(sortInfo.getDirection());
            wrapper.orderBy(true, isAsc, sortInfo.getField());

            // 处理大小写敏感
            if (sortInfo.getIgnoreCase() != null && sortInfo.getIgnoreCase()) {
                wrapper.last("COLLATE utf8_general_ci");
            }

            // 处理自然排序（需要数据库函数支持）
            if (sortInfo.getNaturalSort() != null && sortInfo.getNaturalSort()) {
                wrapper.last("REGEXP_REPLACE(" + sortInfo.getField() + ", '[^0-9]', '')+0");
            }
        }
    }

    /**
     * 验证查询字段是否合法
     */
    private static boolean isValidField(String field) {
        return true;
//        return StringUtils.hasText(field) && ALLOWED_QUERY_FIELDS.matcher(field).matches();
    }

    /**
     * 验证排序字段是否合法
     */
    private static boolean isValidSortField(String field) {
        return true;
//        return StringUtils.hasText(field) && ALLOWED_SORT_FIELDS.matcher(field).matches();
    }
}
